/*
 *  (c) E.S.A.
 */
#include <sys/socket.h>
#include <sys/select.h>
#include <arpa/inet.h>
#include <sys/types.h>

#include <iostream>

#include "client_mode.h"
#include "msg_logger.h"
#include "remote_party.h"
#include "global_data.h"

// connects to one of the remote servers
void* client_thread_main(void* arg)
{ 
	MSG_LOG (DBG, "client thread starting ..");

	remote_srv* remote_server = static_cast<remote_srv*>(arg);

	bool read_size_flag = true; 
	int select_rez, len; 
	uint32_t nbo_mess_size, mess_size = 0;
	int sock;

	fd_set readfds, writefds, exceptfds,
	tmp_readfds, tmp_writefds;
	struct timeval	timeout;

	char rcv_mess[MESS_SIZE];

	// connect to server: 
	remote_server->connect();
	if (remote_server->get_conn_state() == DISCONN)
		goto c_m_thd_end;

	sock = remote_server->get_sock();

	// add the file descriptor sock to the read/write/except set  
	{
		FD_ZERO(&readfds);
		FD_SET(sock, &readfds);

		FD_ZERO(&writefds);
		FD_SET(sock, &writefds);

		FD_ZERO(&exceptfds);
		FD_SET(sock, &exceptfds);
	}

	timeout.tv_sec = 1;
	timeout.tv_usec = 0;

	while (!global.quit_flag) {
		tmp_readfds = readfds;
		tmp_writefds = writefds;

		select_rez = select(sock+1, &tmp_readfds, &tmp_writefds, &exceptfds, &timeout);
		if (select_rez < 0){
			MSG_LOG (ERR,"Error on select");
			goto c_m_thd_end;
		}
		if (select_rez == 0);

		if (FD_ISSET(sock, &tmp_readfds)) {
			MSG_LOG (DBG, "is time to read from sock");

			if (read_size_flag == true){

				// read message size
				len = sizeof(mess_size);
				mess_size =  0;
				int rez = 
					remote_server->read_from_remote_srv(&nbo_mess_size, len);
				if (rez != 0) {
					remote_server->disconnect();
					break;
				}
				if(len == 0){
					MSG_LOG (INFO, "The connection with the other end was clossed.. ");
					break;
				}
				mess_size = ntohl (nbo_mess_size);
				read_size_flag = false;
			} 
			else { 

				// receive data from server
				bzero (rcv_mess, MESS_SIZE * sizeof(char));
				len = mess_size;

				int rez = 
					remote_server->read_from_remote_srv(rcv_mess, len);
				if (rez != 0) {
					remote_server->disconnect();
					break;
				}

				if(len == 0){
					MSG_LOG (INFO, "The connection with the other end was clossed.. ");
					break;
				}


				MSG_LOG (DBG, "MUST read " << mess_size << 
						" read  " << len); 

				////////////////  receive data from REMOTE SERVER (@p) ///////////////////
				sem_wait( &global.recv_buff.empty_sem );
				sem_wait( &global.recv_buff.put_mutex );

				global.recv_buff.mess[global.recv_buff.nextin] = rcv_mess;
				global.recv_buff.nextin = (global.recv_buff.nextin + 1) % CIRCULAR_BUF_SIZE;

				sem_post( &global.recv_buff.put_mutex );
				sem_post( &global.recv_buff.full_sem );

				read_size_flag = true;

			}
		}

		if (FD_ISSET(sock, &tmp_writefds)) {

			remote_server->send_data_to_remote_srv();
		}


	}

	c_m_thd_end:
	remote_server->disconnect();
	MSG_LOG (INFO, "client mode thread finishing .. ");

	return NULL;
}

